#include "modbus.h"
#include "stdio.h"
#include "systick.h"
#include "device_usart.h"
#include "device.h"

/* IWDG init function */
void MX_IWDG_Init(void)
{
    /* confiure FWDGT counter clock: 40KHz(IRC40K) / 64 = 0.625 KHz */
    fwdgt_config(1000, FWDGT_PSC_DIV8);

    /* After 0.2 seconds to generate a reset */
    fwdgt_enable();
}

// 读取异常状态
uchar Read_Exception()
{
    return program_status;
}

void Enter_Boot_Loader(void)
{
    MX_IWDG_Init();
}
void Restart(void)
{
    NVIC_SystemReset();
}
// 诊断
void Diagnose()
{
    ushort subfun = from_little_endian_16(*(ushort *)&uart0_buf[2]); // 子功能代码
    switch (subfun)
    {
    case 0x00: // 原样返回请求数据
    case 0x03: // 改变ASCII结束符
        uart0_len -= 2;
        Response();
        break;

    case 0x01: // 复位通讯端口
        uart0_len = 6;
        subfun = from_little_endian_16(*(ushort *)&uart0_buf[4]);
        Response();

        // 等等发送结束
        while (uart0_tx_pending)
            ;
        if (subfun == 0xFF00) // 清除记录事件
            event_count = 0;

        // 等等停止位发送结束
        Delay_us(10);
        // 重启
        if (subfun == 0xFFFF)
            Enter_Boot_Loader();
        else
            Restart();

        break; // 运行不到此处

    case 0x02: // 返回诊断寄存器
        uart0_len = 6;
        *(ushort *)&uart0_buf[4] = diagnostic;
        Response();
        break;

    case 0x04: // 强迫进入“只听”模式
        ps_listen_only = 1;
        No_Response();
        Log_Event(EVENT_ENTER_LISTEN_ONLY);
        break;

    case 0x0A:                        // 清除计数器和诊断寄存器
        diagnostic = 0;               // 诊断寄存器
        bus_message_count = 0;        // 总线上消息数量
        bus_error_count = 0;          // 总线上通讯错误数量
        bus_exception_count = 0;      // 总线上异常应答数量
        server_message_count = 0;     // 下位机消息数量
        server_no_response_count = 0; // 下位机未响应消息数量
        server_exception_count = 0;   // 下位机异常应答消息数量
        server_busy_count = 0;        // 下位机状态忙数量
        bus_char_overrun_count = 0;   // 总线字符过载（Overrun）数量

        uart0_len -= 2;
        Response();
        break;

    case 0x0B: // 返回总线上消息数量
        uart0_len = 6;
        *(ushort *)&uart0_buf[4] = bus_message_count;
        Response();
        break;

    case 0x0C: // 返回总线上通讯错误数量
        uart0_len = 6;
        *(ushort *)&uart0_buf[4] = bus_error_count;
        Response();
        break;

    case 0x0D: // 返回总线上异常应答数量
        uart0_len = 6;
        *(ushort *)&uart0_buf[4] = bus_exception_count;
        Response();
        break;

    case 0x0E: // 返回下位机消息数量
        uart0_len = 6;
        *(ushort *)&uart0_buf[4] = server_message_count;
        Response();
        break;

    case 0x0F: // 返回下位机未响应消息数量
        uart0_len = 6;
        *(ushort *)&uart0_buf[4] = server_no_response_count;
        Response();
        break;

    case 0x10: // 返回下位机异常应答消息数量
        uart0_len = 6;
        *(ushort *)&uart0_buf[4] = server_exception_count;
        Response();
        break;

    case 0x11: // 返回下位机状态忙数量
        uart0_len = 6;
        *(ushort *)&uart0_buf[4] = server_busy_count;
        Response();
        break;

    case 0x12: // 返回总线字符过载（Overrun）数量
        uart0_len = 6;
        *(ushort *)&uart0_buf[4] = bus_char_overrun_count;
        Response();
        break;

    case 0x14: // 清除过载（Overrun）计数器和标志
        uart0_len -= 2;
        bus_char_overrun_count = 0;
        Response();
        break;

    default: // 未实现或不正确的子功能代码
        Exception_Response(ILLEGAL_FUNCTION);
        break;
    }
}

void Log_Event(uchar event)
{
    event_log[++event_count & MAX_EVENT_MASK] = event;
    if (event_count > MAX_EVENT_MASK)
        event_count = (event_count & MAX_EVENT_MASK) | MAX_EVENT_COUNT;
}
